﻿using MsgManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SampleClient
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class ClientWindow : Window
    {
        private MessageManager manager; // We need MessageManager object to send messages and call other methods.

        private int server_port = 5000;

        public ClientWindow()
        {
            InitializeComponent();

            // Create manager in constructor with desirable name
            // It does not matter what name it is, it's just for you.
            manager = new MessageManager(String.Format("client {0}", MessageManager.LocalIP));

            // Set event handler for message manager
            manager.ServerConnectedSuccess += manager_ServerConnectedSuccess;
            manager.ServerConnectedFailed += manager_ServerConnectedFailed;
            manager.MessageSendSuccess += manager_MessageSendSuccess;
            manager.MessageSendFailed += manager_MessageSendFailed;
            manager.MessageReceived += manager_MessageReceived;
            manager.ClientDisconnected += manager_ClientDisconnected;
        }

        //----------------- Message Manager Events --------------------//

        private void manager_ClientDisconnected(object sender, ClientConnectedArgs e)
        {
            Log(String.Format("{0}: client disconnected", e.Client.IP));
            manager.StopListening(e.Client);
        }

        private void manager_MessageReceived(object sender, MessageReceivedArgs e)
        {
            Client client = e.Client;
            Message message = e.Message;

            Log(String.Format("{0}: message received - {1}: {2}", client.IP, message.MessageType, message.Data));
        }

        private void manager_MessageSendFailed(object sender, MessageSendResultArgs e)
        {
            Log(String.Format("{0}: message send failed", e.Client.IP));
        }

        private void manager_MessageSendSuccess(object sender, MessageSendResultArgs e)
        {
            Log(String.Format("{0}: message send success", e.Client.IP));
        }

        private void manager_ServerConnectedFailed(object sender, ServerConnectedArgs e)
        {
            Log(String.Format("{0}: server connected failed", e.Target.Address.ToString()));
        }

        private void manager_ServerConnectedSuccess(object sender, ServerConnectedArgs e)
        {
            Log(String.Format("{0}: connected to server", e.Client.IP));

            // It is important to invoke action on UI, as it could be called from others thread
            // Because Message Manager works from asynchronously it is important to use invoker
            App.Current.Dispatcher.Invoke((Action)delegate
            {
                btnDisconnect.IsEnabled = true;
                btnSend.IsEnabled = true;
            });    
            
            // Start listening to server
            manager.StartListening(e.Client);
        }

        //----------------------- Form Events --------------------------//

        private void btnConnect_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Parse and create IP End Point from textbox
                string ip_str = txtIP.Text;
                IPAddress ip = IPAddress.Parse(ip_str);
                IPEndPoint target = new IPEndPoint(ip, server_port);

                // Start connecting to server asynchronously
                manager.ConnectToServerAsync(target);

                Log(String.Format("started connecting to server"));
            }
            catch (Exception ex)
            {

            }
        }

        private void btnDisconnect_Click(object sender, RoutedEventArgs e)
        {
            btnDisconnect.IsEnabled = false;
            btnSend.IsEnabled = false;

            manager.StopAllListening();

            Log(String.Format("all clients/server disconnected"));
        }

        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            // Get all client/servers we are listed to from manager
            List<Client> clients = manager.ListenedClients;

            // Create sample message using type and some data/payload
            string data = txtData.Text;
            Message sampleMessage = new Message("sample type", data);

            // Send this message to all connected clients/servers
            foreach (Client client in clients)
            {
                manager.SendMessageAsync(client, sampleMessage);
            }

            Log("message send started");
        }

        private void Log(string log)
        {
            // It is important to invoke action on UI, as it could be called from others thread
            // Because Message Manager works from asynchronously it is important to use invoker
            App.Current.Dispatcher.Invoke((Action)delegate
            {
                txtLog.Text = log + Environment.NewLine + txtLog.Text;
            });          
        }

        private void Window_Closed_1(object sender, EventArgs e)
        {
            // When closing app make sure to stop server and stop listening for other clients
            // As it is done on other threads it would not be closed itself
            manager.StopServer();
            manager.StopAllListening();
        }
    }
}
